package org.wu.framework.web.spring.utils;

import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.resource.ResourceUrlProvider;
import org.wu.framework.core.utils.JsonUtils;
import org.wu.framework.spring.utils.SpringContextHolder;
import org.wu.framework.web.response.Result;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class WebUtils extends org.springframework.web.util.WebUtils{
    private static final Logger log = LoggerFactory.getLogger(WebUtils.class);
    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    private static final PathMatcher pathMatcher = new AntPathMatcher();

    public WebUtils() {
    }

    public static PathMatcher getPathMatcher() {
        return pathMatcher;
    }

    public static boolean isStaticResources(String uri) {
        ResourceUrlProvider resourceUrlProvider = SpringContextHolder.getBean(ResourceUrlProvider.class);
        String staticUri = resourceUrlProvider.getForLookupPath(uri);
        return staticUri != null;
    }

    public static boolean isPathMatch(List<String> patterns, String path) {
        PathMatcher pathMatcher = getPathMatcher();
        Iterator var3 = patterns.iterator();

        String pattern;
        do {
            if (!var3.hasNext()) {
                return false;
            }

            pattern = (String)var3.next();
        } while(!pathMatcher.match(pattern, path));

        return true;
    }

    public static boolean isRequestMatched(List<String> patterns, HttpServletRequest request) {
        String url = request.getRequestURI();
        return isPathMatch(patterns, url);
    }

    public static HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    public static HttpServletResponse getResponse() {
        return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
    }
    public static void renderJson(HttpServletResponse response, Object object) {
        renderJson(response, JsonUtils.toJsonString(object), MediaType.APPLICATION_JSON.toString());
    }

    public static void renderJson(HttpServletResponse response, String string, String type) {
        try {
            response.setContentType(type);
            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
            response.getWriter().print(string);
            response.getWriter().flush();
            response.getWriter().close();
        } catch (IOException var4) {
            log.error("[Herodotus] |- Render response to Json error!");
        }

    }

    public static HttpServletRequest toHttp(ServletRequest request) {
        return (HttpServletRequest)request;
    }

    public static HttpServletResponse toHttp(ServletResponse response) {
        return (HttpServletResponse)response;
    }

    private static boolean isHeaderContainMediaType(ServletRequest request, String headerType, String mediaType) {
        String header = toHttp(request).getHeader(headerType);
        return StringUtils.isNotEmpty(header) && header.contains(mediaType);
    }

    private static boolean isHeaderContainJson(ServletRequest request, String headerType) {
        return isHeaderContainMediaType(request, headerType, "application/json");
    }

    private static boolean isContentTypeHeaderContainJson(ServletRequest request) {
        return isHeaderContainJson(request, "Content-Type");
    }

    private static boolean isAcceptHeaderContainJson(ServletRequest request) {
        return isHeaderContainJson(request, "Accept");
    }

    private static boolean isContainAjaxFlag(ServletRequest request) {
        String xRequestedWith = toHttp(request).getHeader("X-Requested-With");
        return "XMLHttpRequest".equalsIgnoreCase(xRequestedWith);
    }

    public static boolean isAjaxRequest(ServletRequest request) {
        if (!isContentTypeHeaderContainJson(request) && !isAcceptHeaderContainJson(request) && !isContainAjaxFlag(request)) {
            log.trace("[Herodotus] |- Not a Ajax Request!!!!!");
            return false;
        } else {
            log.trace("[Herodotus] |- Is Ajax Request!!!!!");
            return true;
        }
    }

    public static boolean isStaticResourcesRequest(HttpServletRequest request) {
        String requestPath = request.getServletPath();
        return StringUtils.endsWith(requestPath, "html") ? false : isStaticResources(requestPath);
    }

    public static <T> T getPathMatchedObject(String path, Map<String, T> map) {
        PathMatcher pathMatcher = getPathMatcher();
        Iterator var3 = map.keySet().iterator();

        String key;
        do {
            if (!var3.hasNext()) {
                return null;
            }

            key = (String)var3.next();
        } while(!pathMatcher.match(key, path));

        return map.get(key);
    }

    public static String getRequestPayload(ServletRequest request) {
        StringBuilder stringBuilder = new StringBuilder();

        try {
            BufferedReader reader = request.getReader();

            try {
                char[] buffer = new char[1024];

                int length;
                while((length = reader.read(buffer)) != -1) {
                    stringBuilder.append(buffer, 0, length);
                }
            } catch (Throwable var6) {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (Throwable var5) {
                        var6.addSuppressed(var5);
                    }
                }

                throw var6;
            }

            if (reader != null) {
                reader.close();
            }
        } catch (IOException var7) {
            log.error("[Herodotus] |- Get Request Payload Error!");
        }

        return stringBuilder.toString();
    }
}
